#include "GUI_CMD.h"
#include <cstring>
#include "mainwindow.h"
#include "GUI_COM.h"

uint8_t GUI_RxBit=0;
uint8_t GUI_RxBuffer[256]={0};
uint8_t GUI_RxFlag=0;

uint8_t GUI_Status=0;
uint16_t GUI_Data_Len=0;

uint8_t GUI_Timer_Flag=10;
uint8_t GUI_Executing_Flag=0;  	//命令执行Flag

bool GUI_COM_Thread_Flag=false;
GUI_Struct Trans_GUI_to_Struct(uint8_t * buf)
{
    GUI_Struct GUI_Stu;
    GUI_Stu.Flag=false;
    uint8_t i=0;
    uint8_t CHK_Num=0;
    
    uint16_t Data_Len=0;
    uint16_t Check_Sum=0;
    
    GUI_Stu.START[0]=buf[0];
    GUI_Stu.START[1]=buf[1];

    if(GUI_Stu.START[0]!=GUI_START0 || GUI_Stu.START[1]!=GUI_START1)
    {
        return GUI_Stu;
    }

    GUI_Stu.BCNT[0]=buf[2];
    GUI_Stu.BCNT[1]=buf[3];

    Data_Len=(GUI_Stu.BCNT[0]<<8)|(GUI_Stu.BCNT[1]);

    if(!Data_Len)
    {
        return GUI_Stu;
    }

    CHK_Num=Data_Len+6;
    GUI_Stu.STOP[0]=buf[CHK_Num+2];
    GUI_Stu.STOP[1]=buf[CHK_Num+3];

    if(GUI_Stu.STOP[0]!=GUI_STOP0 || GUI_Stu.STOP[1]!=GUI_STOP1)
    {
        return GUI_Stu;
    }

    GUI_Stu.CHK[0]=buf[CHK_Num];
    GUI_Stu.CHK[1]=buf[CHK_Num+1];

    for(i=0;i<CHK_Num;i++)
    {
        Check_Sum=Check_Sum+buf[i];
    }
    
    if((Check_Sum>>8)!=GUI_Stu.CHK[0] || (Check_Sum&0x00FF)!=GUI_Stu.CHK[1])
    {
        return GUI_Stu;
    }

    GUI_Stu.ADDR[0]=buf[4];
    GUI_Stu.ADDR[1]=buf[5];
    
    GUI_Stu.COM=buf[6];

		memcpy(GUI_Stu.DATA,&buf[7],Data_Len-1);

    GUI_Stu.Flag=true;
    return GUI_Stu;
}

uint8_t Trans_GUI_to_Buf(GUI_Struct GUI_Stu,uint8_t * buf)
{
    uint8_t i=0;
    uint8_t CHK_Num=0;
    
    uint16_t Data_Len=0;
    uint16_t Check_Sum=0;

    if(GUI_Stu.START[0]!=GUI_START0 || GUI_Stu.START[1]!=GUI_START1)
    {
        return 0;
    }

    if(GUI_Stu.STOP[0]!=GUI_STOP0 || GUI_Stu.STOP[1]!=GUI_STOP1)
    {
        return 0;
    }

    buf[0]=GUI_Stu.START[0];
    buf[1]=GUI_Stu.START[1];

    buf[2]=GUI_Stu.BCNT[0];
    buf[3]=GUI_Stu.BCNT[1];

    buf[4]=GUI_Stu.ADDR[0];
    buf[5]=GUI_Stu.ADDR[1];

    Data_Len=(GUI_Stu.BCNT[0]<<8)|(GUI_Stu.BCNT[1]);

    if(!Data_Len)
    {
        return 0;
    }

    CHK_Num=Data_Len+6;

    buf[6]=GUI_Stu.COM;

		memcpy(&buf[7],&GUI_Stu.DATA[0],Data_Len-1);

    for(i=0;i<CHK_Num;i++)
    {
        Check_Sum=Check_Sum+buf[i];
    }
    
    buf[CHK_Num]=(Check_Sum&0xFF00)>>8;
    buf[CHK_Num+1]=Check_Sum&0x00FF;

    buf[CHK_Num+2]=GUI_Stu.STOP[0];
    buf[CHK_Num+3]=GUI_Stu.STOP[1];

    return (CHK_Num+4);
}

uint8_t GUI_Slave_Send(GUI_Struct GUI_Stu)
{
    GUI_Struct Stu;
    Stu.START[0]=GUI_START0;
    Stu.START[1]=GUI_START1;
    Stu.BCNT[0]=0;
    Stu.BCNT[1]=0;
    Stu.ADDR[0]=pw->Global_GUI.ADDR[0];
    Stu.ADDR[1]=pw->Global_GUI.ADDR[1];

    uint8_t buf[50];
    memset(buf,0,sizeof(buf)/sizeof(buf[0]));
	uint8_t len=0;

	Stu.BCNT[0]=GUI_Stu.BCNT[0];
	Stu.BCNT[1]=GUI_Stu.BCNT[1];
	
	Stu.COM=GUI_Stu.COM;
	
	Stu.STOP[0]=GUI_STOP0;
	Stu.STOP[1]=GUI_STOP1;
	
	len=(Stu.BCNT[0]<<8)|Stu.BCNT[1];
	
	memcpy(Stu.DATA,GUI_Stu.DATA,len-1);
	
    len=Trans_GUI_to_Buf(Stu,buf);

    emit pw->Set_Sent(Trans_Hex_Buf_to_Str(buf,len));
	return 1;
}

uint8_t GUI_Cannot_Executing(void)
{
    GUI_Struct Stu;
    Stu.COM=0x00;
    Stu.BCNT[0]=0;
    Stu.BCNT[1]=1;
    GUI_Slave_Send(Stu);

    return 1;
}

uint8_t GUI_Error_Executing(void)
{
    GUI_Struct Stu;
    Stu.COM=GUI_COM_Error;
    Stu.BCNT[0]=0;
    Stu.BCNT[1]=1;
    GUI_Slave_Send(Stu);

    return 1;
}

void GUI_COM_Executing(GUI_Struct GUI_Stu)
{
    uint8_t com=0;
    com=GUI_Stu.COM;

    switch (com)
    {
        case GUI_COM_Chart:
        {
            GUI_Chart(GUI_Stu);
            break;
        }
        case GUI_COM_Broadcast:
        {
            GUI_Cannot_Executing();
            break;
        }
        default:
        {
            GUI_Cannot_Executing();
            break;
        }
    }

    GUI_Executing_Flag=0;
}

int16_t Ctrl_GUI_COM(GUI_Struct GUI_Stu)
{
    uint8_t com=0;
    com=GUI_Stu.COM;

    if(GUI_Executing_Flag==1)
    {
        qDebug()<<"[INFO] 正在执行其他命令\n";
        return -1;
    }
    GUI_Executing_Flag=1;


    if(GUI_Stu.ADDR[0]!=pw->Global_GUI.ADDR[0] || GUI_Stu.ADDR[1]!=pw->Global_GUI.ADDR[1])
    {
        emit pw->Set_Log("[INFO] 地址或起始位错误\n");
        GUI_Executing_Flag=0;
        return -1;
    }

    if(!GUI_COM_Thread_Flag)
    {
        GUI_COM_Executing(GUI_Stu);
    }
    else
    {
        pw->GUI_COM_Executing_Stu=GUI_Stu;
        pw->GUI_COM_Thread->startThread();
    }

    return com;
}

void GUI_Reset(bool Reset)
{
    if(GUI_RxFlag)
    {
        uint32_t i=0;
        QList<uint8_t> buf;
        for(i=0;i<GUI_RxFlag;i++)
        {
            buf.append(GUI_RxBuffer[i]);
        }
        QString str = Trans_Hex_Buf_to_Str(buf);
        if(pw->UART_View_Mode)
        {
            QString strDateTime = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss.zzz");
            str = strDateTime+" <--: " + str;
        }

        if(Reset)
        {
            memset(GUI_RxBuffer,0,sizeof(GUI_RxBuffer)/sizeof(GUI_RxBuffer[0]));
            GUI_Status=0;
            GUI_RxFlag=0;
            GUI_Timer_Flag=10;

            pw->Ctrl_GUI_Timer(false);
        }
        else
        {
            str=str+" ...";
        }

        str=str+"\n";
        emit pw->Set_COM(str);
        // TextEdit_Append(pw->com_text,str);

        return;
    }

    memset(GUI_RxBuffer,0,sizeof(GUI_RxBuffer)/sizeof(GUI_RxBuffer[0]));
    GUI_Status=0;
    GUI_RxFlag=0;
    GUI_Timer_Flag=10;

    pw->Ctrl_GUI_Timer(false);

    // HAL_TIM_Base_Stop_IT(&htim5);
}

uint8_t GUI_Judge(void)
{
    if(GUI_Status>=4 && GUI_Timer_Flag<10)
    {
        GUI_Struct GUI_Stu;
        // qDebug()<<"[INFO] 正在解析GUI数据\n";
        GUI_Stu=Trans_GUI_to_Struct(GUI_RxBuffer);
        if(GUI_Stu.Flag)
        {
            qDebug()<<"[INFO] GUI数据有效\n";
            if(Ctrl_GUI_COM(GUI_Stu)!=-1)
            {
                emit pw->Set_Log("[INFO] GUI命令可以执行\n");
                GUI_Reset(true);
                return 2;
            }
            else
            {
                emit pw->Set_Log("[INFO] GUI命令无法执行\n");
                GUI_Reset(true);
                return 0;
            }
        }
        emit pw->Set_Log("[INFO] GUI数据有误\n");
        GUI_Reset(true);
        return 1;
    }
    else
    {
        qDebug()<<"[INFO] 超时未接收到正确的GUI数据\n";
        GUI_Reset(false);
        return 0;  //超时未接收到数据 重新接收
    }
}

void Init_GUI(void)
{
    // GUI_Cannot_Executing();
    memset(GUI_RxBuffer,0,sizeof(GUI_RxBuffer)/sizeof(GUI_RxBuffer[0]));
    GUI_RxFlag=0;
    GUI_RxBit=0;
    GUI_Status=0;
    GUI_Data_Len=0;
    GUI_Timer_Flag=10;

    pw->Ctrl_GUI_Timer(false);
    // HAL_TIM_Base_Stop_IT(&htim5);
}

void GUI_RX_Callback(uint8_t RX)
{
    GUI_RxBit=RX;

    switch(GUI_Status)
    {
    case 0:
    {
        if(GUI_RxBit==GUI_START0)
        {
            GUI_Status++;
        }
        GUI_RxFlag=0;
        break;
    }
    case 1:
    {
        if(GUI_RxBit==GUI_START1 && GUI_RxFlag==1)
        {
            GUI_Status++;
        }
        else
        {
            GUI_Status=0;
            GUI_RxFlag=0;
        }
        break;
    }
    case 2:
    {
        if(GUI_RxFlag==3)
        {
            GUI_Data_Len=(GUI_RxBuffer[2]<<8)|GUI_RxBit;
            GUI_Status++;
            if(!GUI_Data_Len)
            {
                GUI_Status=0;
                GUI_RxFlag=0;
            }
        }
        break;
    }
    case 3:
    {
        if(GUI_RxFlag==(GUI_Data_Len+9))
        {
            if(GUI_RxBit==GUI_STOP1 && GUI_RxBuffer[GUI_Data_Len+8]==GUI_STOP0)
            {
                GUI_Status++;
            }
            else
            {
                GUI_Status=0;
                GUI_RxFlag=0;
            }
        }
        break;
    }
    default:break;
    }

    GUI_RxBuffer[GUI_RxFlag]=GUI_RxBit;
    GUI_RxFlag++;
    GUI_RxBit=0;
    GUI_Timer_Flag=0;

    pw->Ctrl_GUI_Timer(true);
    // HAL_TIM_Base_Start_IT(&htim5);
}

void GUI_Timer_Callback(void)
{
    GUI_Timer_Flag++;
    if(GUI_Timer_Flag>=10)
    {
        GUI_RxFlag=0;
        GUI_Status=0;
        GUI_Timer_Flag=10;

        pw->Ctrl_GUI_Timer(false);
        // HAL_TIM_Base_Stop_IT(&htim5);
    }
}

void GUI_Delay_Judge(uint16_t ms)
{
    QElapsedTimer t;
    t.start();
    while(t.elapsed()<ms && GUI_Status<4)
    {
        QCoreApplication::processEvents();
    }
}
